package se.lth.student.axisandroidcam.client;

import java.util.Map.Entry;

import se.lth.student.axisandroidcam.concurrent.ConcurrentSkipListMap;


import android.app.Activity;

public class SynchronizeThread extends Thread {
	private ConcurrentSkipListMap<Long, DataWrapper> map;
	private final int SIZE = 40;
	private CameraAggregator camAgg;
	private boolean isSynch;
	private boolean forceSynch = false;
	private Activity act;
	public static final long SYNCH_THRESHOLD = 1000;

	public SynchronizeThread(Activity activity, CameraAggregator camAgg) {
		map = new ConcurrentSkipListMap<Long, DataWrapper>();
		this.camAgg = camAgg;
		act = activity;
		isSynch = true;
	}

	public void run() {
		Toolbox.printDebug("Synchronize thread is starting");

		while (true) {
			while (map.size() <= 0) {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
			Entry<Long, DataWrapper> entry = map.pollFirstEntry();
			long prevTime = entry.getKey();
			pushToAggregator(entry.getValue());
			long delay;
			while (true) {

				if (map.size() > 0) {
					entry = map.pollFirstEntry();
					delay = entry.getKey() - prevTime;
					
					if (delay > SynchronizeThread.SYNCH_THRESHOLD && !forceSynch) {						
						pushToAggregator(entry.getValue());
						isSynch = false;
						entry.getValue().isSynch = isSynch;
						Toolbox.printDebug("SynchThread: synch false");
						map.clear();
						break;
					} else if (isSynch || forceSynch) {
						try {
							Toolbox.printDebug("SynchThread: sleep for delay, " + delay + " and then push image");
							if (delay > 1){
								Thread.sleep(delay);
							}
							prevTime = entry.getKey();
							entry.getValue().isSynch = true;
							pushToAggregator(entry.getValue());
						} catch (InterruptedException e1) {
							e1.printStackTrace();
						}
					}
				}

			}
		}
	}

	private void pushToAggregator(final DataWrapper data) {
		act.runOnUiThread(new Runnable() {
			public void run() {
				camAgg.update(null, data);
			}
		});
	}

	public void setSynch(boolean synch){
		Toolbox.printDebug("SynchThread: Forced Synch");
		forceSynch = synch;
	}
	
	public void addImage(DataWrapper data) {
		if (!isSynch && !forceSynch) {
			pushToAggregator(data);
		} else if (map.size() < SIZE) {
			map.put(Toolbox.getTimestamp(data.data), data);
		} else {
			Toolbox.printDebug("SynchThread: Datastructure is full");
		}
	}

}
